package models

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/BertoldVdb/go-ais"
	geojson "github.com/paulmach/go.geojson"
)

// Msg19ToShipInfo
func Msg19ToShipInfo(p *ais.ExtendedClassBPositionReport) *ShipInfo {
	mmsi := fmt.Sprintf("%d", p.UserID)
	mid := parseMID(mmsi)
	iso := mid.GetAlpha2()
	return &ShipInfo{
		MMSI:      mmsi,
		Name:      strings.TrimSpace(p.Name),
		Callsign:  "", //strings.TrimSpace(p.CallSign),
		IMO:       "0",
		MID:       mid,
		ISO:       iso,
		Country:   mid.GetCnName(),
		ShipType:  p.Type,
		Draught:   0, //float32(s.),
		FixType:   p.FixType,
		Eta:       "", //formatEta(s.Eta),
		Dest:      "", //strings.TrimSpace(s.Destination),
		Length:    int32(p.Dimension.A + p.Dimension.B),
		Width:     int32(p.Dimension.C + p.Dimension.D),
		GPSRefPos: []int32{int32(p.Dimension.A), int32(p.Dimension.B), int32(p.Dimension.C), int32(p.Dimension.D)},
	}
}

// ToShipInfo 解析 AIS 静态数据
func Msg5ToShipInfo(s *ais.ShipStaticData) *ShipInfo {
	mmsi := fmt.Sprintf("%d", s.UserID)
	mid := parseMID(mmsi)
	iso := mid.GetAlpha2()
	return &ShipInfo{
		MMSI:      mmsi,
		Name:      strings.TrimSpace(s.Name),
		Callsign:  strings.TrimSpace(s.CallSign),
		IMO:       strconv.FormatUint(uint64(s.ImoNumber), 10),
		MID:       mid,
		ISO:       iso,
		Country:   mid.GetCnName(),
		ShipType:  s.Type,
		Draught:   float32(s.MaximumStaticDraught),
		FixType:   s.FixType,
		Eta:       formatEta(s.Eta),
		Dest:      strings.TrimSpace(s.Destination),
		Length:    int32(s.Dimension.A + s.Dimension.B),
		Width:     int32(s.Dimension.C + s.Dimension.D),
		GPSRefPos: []int32{int32(s.Dimension.A), int32(s.Dimension.B), int32(s.Dimension.C), int32(s.Dimension.D)},
	}
}

// ToGeoFeature
func Msg123ToShipTrack(r *ais.PositionReport) *ShipTrack {
	mmsi := strconv.Itoa(int(r.UserID))
	t := time.Now()

	return &ShipTrack{
		MMSI:      mmsi,
		Lng:       float64(r.Longitude),
		Lat:       float64(r.Latitude),
		Cog:       float64(r.Cog),
		Sog:       float64(r.Sog),
		Heading:   r.TrueHeading,
		Rot:       r.RateOfTurn,
		NavStatus: r.NavigationalStatus,
		Timestamp: t.Unix(),
		Time:      t.Local().Format("15:04:05"),
	}
}

func Msg19ToShipTrack(r *ais.ExtendedClassBPositionReport) *ShipTrack {
	mmsi := strconv.Itoa(int(r.UserID)) //fmt.Sprintf("%d", r.UserID)
	t := time.Now()
	return &ShipTrack{
		MMSI:      mmsi,
		Lng:       float64(r.Longitude),
		Lat:       float64(r.Latitude),
		Cog:       float64(r.Cog),
		Sog:       float64(r.Sog),
		Heading:   r.TrueHeading,
		Rot:       0, //r.RateOfTurn,
		NavStatus: 0, //r.NavigationalStatus,
		Timestamp: t.Unix(),
		Time:      t.Local().Format("15:04:05"),
	}
}

func Msg18ToShipTrack(r *ais.StandardClassBPositionReport) *ShipTrack {
	mmsi := strconv.Itoa(int(r.UserID)) //fmt.Sprintf("%d", r.UserID)
	t := time.Now()
	return &ShipTrack{
		MMSI:      mmsi,
		Lng:       float64(r.Longitude),
		Lat:       float64(r.Latitude),
		Cog:       float64(r.Cog),
		Sog:       float64(r.Sog),
		Heading:   r.TrueHeading,
		Rot:       0, //r.RateOfTurn,
		NavStatus: 0, //r.NavigationalStatus,
		Timestamp: t.Unix(),
		Time:      t.Local().Format("15:04:05"),
	}
}

var partA = make(map[uint32]*ais.StaticDataReportA)
var partB = make(map[uint32]*ais.StaticDataReportB)

func Msg24ToShipInfo(p *ais.StaticDataReport) *ShipInfo {
	if p.PartNumber {
		//use part B
		partB[p.UserID] = &p.ReportB
		if a, ok := partA[p.UserID]; ok {
			return msg24ToShipInfo(p.UserID, a, &p.ReportB)
		}
	} else {
		partA[p.UserID] = &p.ReportA
		if b, ok := partB[p.UserID]; ok {
			return msg24ToShipInfo(p.UserID, &p.ReportA, b)
		}
	}
	return nil
}

// Msg24ToShipInfo from ais msg24 A+B generate ShipInfo
func msg24ToShipInfo(userID uint32, a *ais.StaticDataReportA, b *ais.StaticDataReportB) *ShipInfo {
	mmsi := fmt.Sprintf("%d", userID)
	mid := parseMID(mmsi)
	iso := mid.GetAlpha2()
	return &ShipInfo{
		MMSI:      mmsi,
		Name:      strings.TrimSpace(a.Name),
		Callsign:  strings.TrimSpace(b.CallSign),
		IMO:       "0", //strconv.FormatUint(uint64(s.ImoNumber), 10),
		MID:       mid,
		ISO:       iso,
		Country:   mid.GetCnName(),
		ShipType:  b.ShipType,
		Draught:   0, //float32(s.),
		FixType:   b.FixType,
		Eta:       "", //formatEta(s.Eta),
		Dest:      "", //strings.TrimSpace(s.Destination),
		Length:    int32(b.Dimension.A + b.Dimension.B),
		Width:     int32(b.Dimension.C + b.Dimension.D),
		GPSRefPos: []int32{int32(b.Dimension.A), int32(b.Dimension.B), int32(b.Dimension.C), int32(b.Dimension.D)},
	}
}

// Msg123ToTrackFeature
func Msg123ToTrackFeature(mmsi string, r *ais.PositionReport) *geojson.Feature {
	p := geojson.NewPointGeometry([]float64{float64(r.Longitude), float64(r.Latitude)})
	f := geojson.NewFeature(p)

	// t, _ := c.st.GetTime(r.Timestamp)
	t := time.Now()

	f.SetProperty("mmsi", mmsi)
	f.SetProperty("cog", r.Cog)
	f.SetProperty("sog", r.Sog)
	f.SetProperty("heading", r.TrueHeading)
	f.SetProperty("rot", r.RateOfTurn)
	f.SetProperty("navStatus", r.NavigationalStatus)
	f.SetProperty("timestamp", t.Unix())
	f.SetProperty("time", t.Local().Format("15:04:05"))
	return f
}
